/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including but not limited to the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to provide persons with access to the Software
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGE OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

<template>
  <div class='player'>
    <div class='time-schedule'>
      <div 
        class='progress-bar' 
        v-interaction='getHandles()'
      >
        <span
          :class="['progress-bar-time']"
          :style="{ width: getWidth + '%' }"
        ></span>
        <span
          ref='scheduleRef'
          :class="['progress-bar-bg']"
        ></span>
        <span
          draggable='true'
          v-interaction='{
            handlers: {
              onDragStart: handleDragStart,
            },
            configs: {
              enableDrag: true,
            },
          }'
          class='drag-start'
          :style="{ left: getWidth - 1 + '%' }"
        ></span>
      </div>
      <div class='time'>
        <span class='current-time'>{{ musicPlayTime }}</span>
        <span class='duration'>{{ musicTime }}</span>
      </div>
    </div>
    <div class='play-icon'>
      <img src='../../assets/images/repeat.svg' />
      <img @click='previousTrack' src='../../assets/images/left.svg' />
      <img
        v-if='isPlay === 1'
        @click='playMusic(PAUSE)'
        src='../../assets/images/pause.svg'
      />
      <img
        v-if='isPlay === 0'
        @click='playMusic(PLAY)'
        src='../../assets/images/play.svg'
      />
      <img
        @click='theNextSong'
        src='../../assets/images/forward_end_fill.svg'
      />
      <img src='../../assets/images/music_note_list.svg' />
    </div>
    <div class='play-nav-icon'>
      <img src='../../assets/images/share_play.svg' />
      <img src='../../assets/images/bell.svg' />
      <img src='../../assets/images/arrow_down_circle.svg' />
      <img src='../../assets/images/dot.svg' />
    </div>
  </div>
</template>

<script lang='ts' setup>
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
import {
  ref,
  defineProps,
  onMounted,
  defineEmits,
  nextTick,
  inject,
  onBeforeUnmount,
} from 'vue';
import { PointerState } from '@hadss/web_uni_input';
import { musicListType } from '../../utils/common';

const router = useRouter();
const store = useStore();
const player = inject<any>('$musicPlayer');
const musicTime = ref<string>('');
const musicPlayTime = ref<string>('00:00');
const musicList = ref<musicListType[]>(store.state.musicList);
const oneMusic = ref<object>({});
const getWidth = ref<number>(0);
const scheduleRef = ref(null);
const scheduleWidth = ref(0);
const startX = ref<number>(0);
const dragTimer = ref(null);
const PLAY = 1;
const PAUSE = 0;
const props = defineProps({
  deviceType: {
    type: String,
    default: 'mobile',
  },
  isPlay: {
    type: Number,
    default: 0,
  },
  musicId: {
    type: Number,
    default: 1,
  },
  musicListNum: {
    type: Number,
    default: 50,
  },
});
const isPlay = ref<number>(props.isPlay);
const musicId = ref<number>(props.musicId);
const emit = defineEmits<{
  (e: 'updateMusic', message: number): void;
  (e: 'updateIsPlay', message: number): void;
}>();

// 播放或暂停
const playMusic = (value: number) => {
  isPlay.value = value;
  if (value === 0) {
    player.pause();
  } else {
    player.play();
    player.onTimeUpdate(handleTimeUpdate);
  }
  emit('updateIsPlay', isPlay.value);
};

const handleClick = (e: PointerState) => {
  const currentProgress =
    ((e.windowX - startX.value) / scheduleWidth.value) * 100;
  musicProgress(currentProgress);
};

const handleDragStart = (e: DragEvent) => {
  e.dataTransfer.setData('text/plain', '');
  const img = new Image();
  img.src =
    '';
  e.dataTransfer?.setDragImage(img, 0, 0);
  e.dataTransfer.effectAllowed = 'move';
};

const handleDragMove = (e: DragEvent) => {
  if (dragTimer.value) {
    clearTimeout(dragTimer.value);
  }
  const currentProgress =
    ((e.clientX - startX.value) / scheduleWidth.value) * 100;
  musicProgress(currentProgress);
  e.preventDefault();
};

const handleScrollStart = (e: PointerState) => {
  const currentProgress =
    ((e.windowX - startX.value) / scheduleWidth.value) * 100;
  musicProgress(currentProgress);
};

const handleDrop = (e: DragEvent) => {
  e.preventDefault();
};

// 上一曲
const previousTrack = (): void => {
  player.pause();
  updateMusic(-1);
};
// 下一曲
const theNextSong = (): void => {
  player.pause();
  updateMusic(1);
};

const updateMusic = (num: number): void => {
  const musicIndex = musicList.value.findIndex(
    (item) => item.id === musicId.value
  );
  if (
    (num > 0 && musicIndex <= musicList.value.length) ||
    (num < 0 && musicIndex !== 0)
  ) {
    oneMusic.value = musicList.value[musicIndex + num];
    musicId.value = musicList.value[musicIndex + num].id;
    player.seekTo(0); // 将播放位置重置到开头
    player.play();
    player.onTimeUpdate(handleTimeUpdate);
    isPlay.value = 1;
    emit('updateIsPlay', isPlay.value);
    emit('updateMusic', musicId.value);
  }
  return;
};

const seek = (num: number): void => {
  const newTime = player.getCurrentTime() + num;
  player.seekTo(newTime);
  musicPlayTime.value = formatTime(newTime);
};

const musicProgress = (currentProgress: number): void => {
  if (currentProgress > 0 && currentProgress <= 100) {
    const newTime = (currentProgress * player.getDuration()) / 100;
    getWidth.value = currentProgress;
    player.seekTo(newTime);
    musicPlayTime.value = formatTime(newTime);
  }
};

const formatTime = (time: number): string => {
  const minutes = Math.floor(time / 60);
  const seconds = Math.floor(time % 60);
  return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
};
const keyIncident = (ev: KeyboardEvent): void => {
  ev.preventDefault();
  switch (ev.key) {
    case 'ArrowUp':
      previousTrack();
      break;
    case 'ArrowDown':
      theNextSong();
      break;
    case 'ArrowLeft':
      if (player.getCurrentTime() - 5 < 0) {
        player.seekTo(0);
        musicPlayTime.value = formatTime(0);
      } else {
        seek(-5);
      }
      break;
    case 'ArrowRight':
      if (player.getCurrentTime() + 5 > player.getDuration()) {
        player.seekTo(player.getDuration());
        musicPlayTime.value = formatTime(player.getDuration());
      } else {
        seek(5);
      }
      break;
    case 'Enter':
      isPlay.value = 1;
      player.play();
      emit('updateIsPlay', isPlay.value);
      break;
    case 'Escape':
      router.push({
        path: '/musicList',
        query: {
          isPlay: isPlay.value,
          musicId: musicId.value,
        },
      });
      break;
    case ' ':
      isPlay.value = 0;
      player.pause();
      emit('updateIsPlay', isPlay.value);
      break;
  }
};

const handleTimeUpdate = (time: number, dur: number): void => {
  const progress = (time / dur) * 100;
  getWidth.value = progress;
  musicPlayTime.value = formatTime(time);
};

const screenSize = (): void => {
  if (scheduleRef.value && scheduleRef.value.getBoundingClientRect()) {
    startX.value = scheduleRef.value.getBoundingClientRect().left;
    const style = window.getComputedStyle(scheduleRef.value);
    const width = parseFloat(style.width);
    scheduleWidth.value = width;
  }
};

const getHandles = () => {
  return {
    handlers: {
      onDragMove: handleDragMove,
      onClick: handleClick,
      onScroll: handleScrollStart,
      onDrop: handleDrop,
    },
    configs: {
      enableDrag: true,
      enableClick: true,
      enableScroll: true,
    },
  };
};

onMounted(() => {
  player.pause();
  player.seekTo(0);
  const MusicList = sessionStorage.getItem('musicList');
  if (MusicList) {
    musicList.value = JSON.parse(MusicList);
    store.commit('addMusiclist', musicList.value);
  }
  oneMusic.value = musicList.value.find((item) => item.id === musicId.value);
  musicTime.value = formatTime(player.getDuration());
  if (player.getCurrentTime() > 0 && isPlay.value === 0) {
    const progressPercentage =
      (player.getCurrentTime() / player.getDuration()) * 100;
    getWidth.value = progressPercentage;
    musicPlayTime.value = formatTime(player.getCurrentTime());
  }
  if (isPlay.value) {
    player.play();
    player.onTimeUpdate(handleTimeUpdate);
  } else {
    player.pause();
  }
  document.addEventListener('keyup', keyIncident);
  nextTick(() => {
    screenSize();
    window.addEventListener('resize', screenSize);
  });

  onBeforeUnmount(() => {
    player.pause();
    player.seekTo(0);
    document.removeEventListener('keyup', keyIncident);
    window.removeEventListener('resize', screenSize);
  });
});
</script>

<style lang='less' scoped>
@import './index.less';
</style>